﻿#include "udpassistant.h"
#include "ui_udpassistant.h"

#include <QIntValidator>
#include <QHostInfo>
#include "myserver.h"
#include <QMessageBox>
#include "mysocket.h"

UdpAssistant::UdpAssistant(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::UdpAssistant)
{
    ui->setupUi(this);

    qDebug()<<"UdpAssistant char size:"<<sizeof (char);

    m_udpSocket=nullptr;
    //信息收发文本框高度3：1
    ui->splitter_2->setStretchFactor(0, 3);
    ui->splitter_2->setStretchFactor(1, 1);

    //ip校验正则
    QRegExp regExpIP("((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])[\\.]){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])");

    //设置端口输入校验
    ui->lineEdit_udpLocalPort->setValidator(new QIntValidator(0,65535));
    ui->lineEdit_udpRemotePort->setValidator(new QIntValidator(0,65535));
    //设置IP输入校验
    ui->lineEdit_GroupIp->setValidator(new QRegExpValidator(regExpIP ,ui->lineEdit_GroupIp));
    ui->lineEdit_udpLocalIP->setValidator(new QRegExpValidator(regExpIP ,ui->lineEdit_udpLocalIP));
    ui->lineEdit_udpRemoteIP->setValidator(new QRegExpValidator(regExpIP ,ui->lineEdit_udpRemoteIP));
    //显示本地ip
    QString localip = this->sockethelper->Get_LocalIp();
    ui->lineEdit_udpLocalIP->setText(localip);
    ui->lineEdit_udpRemoteIP->setText(localip);
    //UDP通讯模式组
    m_udpModeGroup = new QButtonGroup(this);
    //连接信号和槽，radiobutton改变udp模式
    connect(m_udpModeGroup, SIGNAL(buttonClicked(int)),this,SLOT(on_udpModeChange(int)));
}

UdpAssistant::~UdpAssistant()
{

    if(m_udpSocket!=nullptr)
    {
        m_udpSocket->abort();
        delete m_udpSocket;
    }
    delete ui;
}
//udp接收消息
void UdpAssistant::UdpReadData()
{
    //获取发来的数据
    QByteArray datagram;
    while (m_udpSocket->hasPendingDatagrams())
    {
        //等待接收的字节数
        int sizeLen=static_cast<int>(m_udpSocket->pendingDatagramSize());
        datagram.resize(sizeLen);
        //读取
        m_udpSocket->readDatagram(datagram.data(),datagram.size());

    }

    QString data;
    //hex
    if(ui->chk_udpRecHex->isChecked())
    {
//        this->ByteToHexString(data,datagram);
    }
    else//普通字符串
    {
        data=QString::fromLocal8Bit(datagram);
    }
    //显示
    ui->text_udpRec->insertPlainText(data);
    ui->text_udpRec->moveCursor(QTextCursor::End);
}

//点击udp绑定/解绑
void UdpAssistant::on_btn_udpBind_clicked()
{
    //解绑udp
    if(this->m_udpSocket!=nullptr)
    {
        //断开信号槽
        m_udpSocket->disconnect();
        //组播模式
        if(ui->chk_udpGroup->isChecked())
        {
            //获取组播的Ip
            QHostAddress ip(ui->lineEdit_GroupIp->text());
            //退出组
            m_udpSocket->leaveMulticastGroup(ip);
            ui->lineEdit_GroupIp->setEnabled(true);
        }
        m_udpSocket->abort();//关闭udp
        m_udpSocket->deleteLater();//释放
        m_udpSocket=nullptr;
        //更新UI
        ui->text_udpRec->appendPlainText("udp已解绑"+QString("[%1：%2]").arg(ui->lineEdit_udpLocalIP->text()).arg(ui->lineEdit_udpLocalIP->text()));
        ui->btn_udpBind->setText("绑定");
        ui->btn_udpBind->setIcon(QIcon(":/Resource/Img/start36x36.png"));
        ui->groupBox_udp->setEnabled(true);
        ui->lineEdit_udpLocalIP->setEnabled(true);
        ui->lineEdit_udpLocalPort->setEnabled(true);
    }
    //绑定端口
    else
    {
        //获取本地端口
        bool ok;
        quint16 port=ui->lineEdit_udpLocalPort->text().toUShort(&ok);
        if(!ok)
        {
            QMessageBox::warning(this,"错误","本地端口设置有误，请重新输入");
            return;
        }
        //获取本地Ip
        QHostAddress localip(ui->lineEdit_udpLocalIP->text());
        localip.toIPv4Address(&ok);
        if(!ok)
        {
            QMessageBox::warning(this,"错误","本地ip设置有误，请重新输入");
            return;
        }

        this->m_udpSocket=new QUdpSocket(this);
        //绑定端口
        this->m_udpSocket->bind(localip,port,QAbstractSocket::ShareAddress);
        //连接接收信号槽
        connect(m_udpSocket,SIGNAL(readyRead()),this,SLOT(UdpReadData()));
        //更新UI
        ui->text_udpRec->appendPlainText("udp已绑定"+QString("[%1：%2]\r\n").arg(
                                             ui->lineEdit_udpLocalIP->text()).arg(
                                             ui->lineEdit_udpLocalIP->text()));
        ui->btn_udpBind->setText("解绑");
        ui->btn_udpBind->setIcon(QIcon(":/Resource/Img/stop36x36.png"));
        ui->groupBox_udp->setEnabled(false);
        ui->lineEdit_udpLocalIP->setEnabled(false);
        ui->lineEdit_udpLocalPort->setEnabled(false);
    }


}

//改变udp通信模式
void UdpAssistant::on_udpModeChange(int id)
{
    switch (id)
    {
    //单播
    case 0:
        ui->lineEdit_udpRemoteIP->setEnabled(true);
        ui->lineEdit_udpLocalPort->setEnabled(true);
        ui->lineEdit_udpLocalIP->setEnabled(true);
        ui->lineEdit_udpLocalPort->setEnabled(true);
        ui->chk_udpGroup->setChecked(false);
        ui->chk_udpGroup->setEnabled(false);
        ui->lineEdit_GroupIp->setEnabled(false);
        break;
        //组播
    case 1:
        ui->lineEdit_udpRemoteIP->setEnabled(true);
        ui->lineEdit_udpLocalPort->setEnabled(true);
        ui->lineEdit_udpLocalIP->setEnabled(true);
        ui->lineEdit_udpLocalPort->setEnabled(true);
        ui->chk_udpGroup->setEnabled(true);
        ui->lineEdit_GroupIp->setEnabled(true);
        break;
        //广播
    case 2:
        ui->lineEdit_udpRemoteIP->setEnabled(false);
        ui->lineEdit_udpLocalPort->setEnabled(false);
        ui->lineEdit_udpLocalIP->setEnabled(true);
        ui->lineEdit_udpLocalPort->setEnabled(true);
        ui->chk_udpGroup->setChecked(false);
        ui->chk_udpGroup->setEnabled(false);
        ui->lineEdit_GroupIp->setEnabled(false);
        break;
    default:break;
    }
}

//清除udp接收
void UdpAssistant::on_btn_udpClearRec_clicked()
{
    ui->text_udpRec->clear();
}

//清除udp发送
void UdpAssistant::on_btn_udpClearSend_clicked()
{
    ui->text_udpSend->clear();
}

//点击udp发送
void UdpAssistant::on_btn_udpSend_clicked()
{
    //获取远程端口
    bool ok;
    quint16 port=ui->lineEdit_udpRemotePort->text().toUShort(&ok);
    if(!ok)
    {
        QMessageBox::warning(this,"错误","远程端口设置有误，请重新输入");
        return;
    }

    QByteArray byteArray;
    QString data=ui->text_udpSend->toPlainText();
    //Hex发送
    if(ui->chk_udpSendHex->isChecked())
    {
        //hex字符串转字节
//        if(!HexStringToByte(data,byteArray))
//        {
//            QMessageBox::information(this,"提示","输入的十六进制字符串有误，请重新输入");
//            return;
//        }
    }
    //普通字符串发送
    else
    {
        byteArray= data.toLocal8Bit();
    }


    //单播
    if(ui->rad_udpSingle->isChecked())
    {
        //获取远程Ip
        QHostAddress remoteip(ui->lineEdit_udpRemoteIP->text());
        remoteip.toIPv4Address(&ok);
        if(!ok)
        {
            QMessageBox::warning(this,"错误","远程ip设置有误，请重新输入");
            return;
        }

        //发送
        m_udpSocket->writeDatagram(byteArray,remoteip,port);

    }
    //组播
    else if(ui->rad_udpGroup->isChecked())
    {
        //获取远程Ip
        QHostAddress remoteip(ui->lineEdit_udpRemoteIP->text());
        remoteip.toIPv4Address(&ok);
        if(!ok)
        {
            QMessageBox::warning(this,"错误","远程ip设置有误，请重新输入");
            return;
        }
        //D类IP地址的范围为224.0.0.0～239.255.255.255。前4比特固定为1110，后28比特是组播组地址标识(ID)
        QPair<QHostAddress, int> subnet = QHostAddress::parseSubnet("224.0.0.0/4");
        bool is_DClass = remoteip.isInSubnet(subnet);
        if(!is_DClass)
        {
            QMessageBox::warning(this,"错误","远程ip应在D类IP地址范围224.0.0.0～239.255.255.255内，请重新输入");
            return;
        }
        //发送
        m_udpSocket->writeDatagram(byteArray,remoteip,port);
    }
    //广播
    else
    {
        //发送
        m_udpSocket->writeDatagram(byteArray,QHostAddress::Broadcast,port);
    }
}

//加入\退出组播
void UdpAssistant::on_chk_udpGroup_clicked(bool checked)
{
    static QHostAddress currentIP;
    if(checked)
    {
        if(this->m_udpSocket == nullptr)
        {
            QMessageBox::warning(this,"警告","请先绑定本地IP和端口");
            ui->chk_udpGroup->setChecked(false);
            return;
        }
        //获取组播Ip
        bool ok;
        QHostAddress groupip(ui->lineEdit_GroupIp->text());
        groupip.toIPv4Address(&ok);
        if(!ok)
        {
            QMessageBox::warning(this,"错误","组播IP输入有误，请重新输入");
            ui->chk_udpGroup->setChecked(false);
            return;
        }
        //D类IP地址的范围为224.0.0.0～239.255.255.255。前4比特固定为1110，后28比特是组播组地址标识(ID)
        QPair<QHostAddress, int> subnet = QHostAddress::parseSubnet("224.0.0.0/4");
        bool is_DClass = groupip.isInSubnet(subnet);
        if(!is_DClass)
        {
            QMessageBox::warning(this,"错误","组播IP应在D类IP地址范围224.0.0.0～239.255.255.255内，请重新输入");
            ui->chk_udpGroup->setChecked(false);
            return;
        }
        ui->lineEdit_GroupIp->setEnabled(false);
        //加入组
        m_udpSocket->joinMulticastGroup(groupip);
        currentIP = groupip;//记录ip
    }
    else
    {
        //退出组
        m_udpSocket->leaveMulticastGroup(currentIP);
        ui->lineEdit_GroupIp->setEnabled(true);
    }
}
